#include "ET++.ph"
#include "Converter.h"

#include "Class.h"
#include "Data.h"
#include "Bitmap.h"
#include "DevBitmap.h"
#include "String.h"
#include "TypeMatcher.h"
#include "ET_stdio.h"

static const Symbol cDocTypeSunBitmap("SUNBITMAP");
static TypeMatcher matcher(cDocTypeSunBitmap, "icon", "/* Format_version=1", TRUE);

//---- SunIconConverter --------------------------------------------------------

class SunIconConverter : public Converter {
public:
	MetaDef(SunIconConverter);
	SunIconConverter()
		{ }
	const char *AsString()
		{ return "Sun Icon"; }
	Object *DoConvert1(FILE *fp);
	Object *Convert(Data *data, Class *want);
	bool CanConvert(Data *data, Class *want)
		{ return data->Type() == cDocTypeSunBitmap && want == Meta(Bitmap); }
};

NewMetaImpl0(SunIconConverter,Converter);

Object *SunIconConverter::DoConvert1(FILE *fp)
{
	int tmp, version= 1, width= 0, height= 0, depth= 1, bitsperitem= 16;
	int b, x= 0, y= 0, bytesperline, bytesperitem, itemsperline, imbytesperline;
	u_long mask, m, d;
	char buf[200], c;
	Bitmap *BM;
	DevBitmap *dbm;

	while (fscanf(fp, "%s", buf) == 1) {
		if (sscanf(buf, "Format_version=%d", &version) == 1)
			continue;
		if (sscanf(buf, "Width=%d", &width) == 1)
			continue;
		if (sscanf(buf, "Height=%d", &height) == 1)
			continue;
		if (sscanf(buf, "Depth=%d", &depth) == 1)
			continue;
		if (sscanf(buf, "Valid_bits_per_item=%d", &bitsperitem) == 1)
			continue;
		if (strcmp(buf, "*/") == 0)
			break;
	}

	if (width <= 0 || height <= 0)
		return 0;
		
	BM= new Bitmap(Point(width, height), depth);
	dbm= BM->GetDevBitmap();
	itemsperline= (width-1) / bitsperitem + 1;
	bytesperitem= bitsperitem / 8;
	bytesperline= itemsperline * bytesperitem;
	mask= 0xff << (bytesperitem-1)*8;
	imbytesperline= dbm->BytesPerLine();
	byte *bbuf= new byte[bytesperline],
		*bp= bbuf;
	BitmapInfo bi(BM->Size(), depth, 1);

	while (fscanf(fp, "%i%c", &tmp, &c) >= 1) {
		m= mask;
		for (b= bytesperitem-1; b >= 0; b--) {
			d= (tmp & m) >> (b*8);
			m >>= 8;
			if (x < imbytesperline && y < height)
				*bp++= (byte) d;
			x++;
			if (x == bytesperline) {
				dbm->SetRow(&bi, y++, bbuf);
				bp= bbuf;
				x= 0;
			}
		}
	}

	delete bbuf;

	return BM;
}

Object *SunIconConverter::Convert(Data *data, Class*)
{
	FILE *fp;
	if (fp= fopen((char*) data->Name(), "r")) {
		Object *op= DoConvert1(fp);
		fclose(fp);
		if (op == 0)
			fprintf(stderr, "error\n");
		return op;
	}
	return 0;
}
